/**
 * @file bsp_int.h
 * @author 何传喜
 * @brief 中断驱动文件
 * @version 0.1
 * @date 2023-09-06
 * @note 2023-09-06 初创建
 * @copyright Copyright (c) 2023
 * 
 */
#include "bsp_int.h"

/* 中断嵌套计数器 */
static unsigned int irqNesting;

/* 中断服务函数表 */
static sys_irq_handle_t irqTable[NUMBER_OF_INT_VECTORS];

/**
 * @brief 中断初始化函数
 * @param 无
 * @return 无
 * 
 */
void int_init(void)
{
    GIC_Init(); /* 初始化 GIC */
    system_irqtable_init(); /* 初始化中断表 */
    __set_VBAR((uint32_t)0x87800000); /* 中断向量表偏移 */
}

/**
 * @brief 初始化中断服务函数表
 * @param 无
 * @return 无
 * 
 */
void system_irqtable_init(void)
{
    irqNesting = 0;

    /* 先将所有的中断服务函数设置为默认值 */
    for (unsigned int i = 0; i < NUMBER_OF_INT_VECTORS; i++) {
        system_register_irqhandler((IRQn_Type)i, default_irqhandler, NULL);
    }
}

/**
 * @brief 给指定的中断号注册中断服务函数
 * 
 * @param irq 要注册的中断号
 * @param handler 要注册的中断处理函数
 * @param userParam 中断服务处理函数参数
 * @return 无
 */
void system_register_irqhandler(IRQn_Type irq, 
                                system_irq_handler_t handler,
                                void *userParam)
{
    irqTable[irq].irqHandler = handler;
    irqTable[irq].userParam = userParam;
}

/**
 * @brief C 语言中断服务函数，irq 汇编中断服务函数会调用此函数，此函数通过在中断服务列
 *        表中查找指定中断号对应的中断处理函数并执行
 * 
 * @param giccIar 中断号
 * @return 无
 */
void system_irqhandler(unsigned int giccIar)
{
    uint32_t intNum = giccIar & 0x3FFUL;
    /* 检查中断号是否符合要求 */
    if ((intNum == 1020) || (intNum >= NUMBER_OF_INT_VECTORS)) {
        return;
    }
    irqNesting++; /* 中断嵌套计数器加一 */

    /* 根据传递进来的中断号，在 irqTable 中调用确定的中断服务函数 */
    irqTable[intNum].irqHandler(intNum, irqTable[intNum].userParam);

    irqNesting--; /* 中断执行完成，中断嵌套计数器减一 */
}

/**
 * @brief 默认中断服务函数
 * 
 * @param giccIar 中断号
 * @param userParam 中断服务处理函数参数
 * @return 无
 */
void default_irqhandler(unsigned int giccIar, void *userParam)
{
    while (1) {
        
    }
}
